MATH 318 Final Project: The Effect of World Cup on Stock Price and
Trading Activity
library(tidyverse)
library(dplyr)
library(MASS)
library(lubridate)
library(stringr)
library(GGally)
library(knitr)
library(kableExtra)
library(tidyquant)
Loading required package: PerformanceAnalytics
Loading required package: xts
Loading required package: zoo
Attaching package: ‘zoo’
The following objects are masked from ‘package:base’:
as.Date, as.Date.numeric
################################### WARNING ###################################
# We noticed you have dplyr installed. The dplyr lag() function breaks how #
# base R's lag() function is supposed to work, which breaks lag(my_xts). #
# #
# Calls to lag(my_xts) that you enter or source() into this session won't #
# work correctly. #
# #
# All package code is unaffected because it is protected by the R namespace #
# mechanism. #
# #
# Set `options(xts.warn_dplyr_breaks_lag = FALSE)` to suppress this warning. #
# #
# You can use stats::lag() to make sure you're not using dplyr::lag(), or you #
# can add conflictRules('dplyr', exclude = 'lag') to your .Rprofile to stop #
# dplyr from breaking base R's lag() function. #
################################### WARNING ###################################
Attaching package: ‘xts’
The following objects are masked from ‘package:dplyr’:
first, last
Attaching package: ‘PerformanceAnalytics’
The following object is masked from ‘package:graphics’:
legend
Loading required package: quantmod
Loading required package: TTR
Registered S3 method overwritten by 'quantmod':
method from
as.zoo.data.frame zoo
Introduction
Our goal in this project was to explore the effect the FIFA World Cup
has on the stock market. In researching to prepare, we found that the
World Cup has a generally negative impact on the market. According to an
article from MarketWatch, a country's average market return
significantly drops after their team is eliminated from the Cup. The
inverse can't be said for team wins, which leads to the overall market
decreasing. Our interest was to investigate the market trends,
specifically regarding the S&P 500, in relation to the times of
World Cup games.Â
Exploration
candleStick_plot<-function(symbol,from,to){
tq_get(symbol,
from = from,
to = to,
warnings = FALSE) %>% mutate(greenRed=ifelse(open-close>0,
"Red",
"Green")) %>%
ggplot()+
geom_segment(aes(x = date,
xend=date,
y =open,
yend =close,
colour=greenRed),
size=3)+
theme_tq()+
geom_segment(aes(x = date,
xend=date,
y =high,
yend =low,
colour=greenRed))+
scale_color_manual(values=c("Forest Green","Red"))+
ggtitle(paste0(symbol," (",from," - ",to,")"))+
theme(legend.position ="none",
axis.title.y = element_blank(),
axis.title.x=element_blank(),
axis.text.x = element_text(angle = 90, vjust = 0.5, hjust=1),
plot.title= element_text(hjust=0.5))
}
candleStick_plot("SPY", from = '2002-05-31', to = '2002-06-30')
Warning: Using `size` aesthetic for lines was deprecated in ggplot2 3.4.0.
Please use `linewidth` instead.

candleStick_plot("SPY", from = '2006-06-09', to = '2006-07-09')

candleStick_plot("SPY", from = '2010-06-11',to = '2010-07-11')

candleStick_plot("SPY", from = '2014-06-12',to = '2014-07-13')

Load Data
spydata = as_tibble(read.csv("1_min_SPY_2008-2021.csv"))
worldcupmatches = as_tibble(read.csv("WorldCupMatches.csv"))
We were interested in looking at the general price of the market
during the world cup, to confirm if our data shows the proposed trend of
decreased price during the World Cup we found in our research. To do
this we used a graphing method called candlesticks plots. These plots
show the average and variation of the price over a given month. Each
plot spanned the month of the World Cup for the years 2002, 2006, 2010,
2014. Both the graph for 2002 and 2010 display a generally decreasing
trend throughout the month. However, the 2006 and 2014 graphs instead
show a general increase in price over time. To better understand trends
in the data, we then looked closer at information from singular
games.Â
Helper Functions
Get Only Spy Data for a Specific Game
#Clean SpyData Per Game
getSpyDataWithinRangeofGame = function(spydata,game_date,range){
rangeInSeconds = 60 * 60 * range
return(filter(spydata, (date >= game_date - rangeInSeconds) & (date <= game_date + rangeInSeconds)))
}
Check if there is Spy data for a game
hasSpyDataWithinRangeOfGame = function(spydata, game_dates, range){
list = c()
for(game_date in 1:length(game_dates)){
list = append(list, nrow(getSpyDataWithinRangeofGame(spydata, game_date = game_dates[game_date], range)) != 0)
}
return(list)
}
Get Spy Data combined with Game Data for a set of Games
#Clean Spydata Per Worldcup Returns a set of spydata with their corresponding game data
getSpyAndGameDataWithinWorldcup = function(worldcup, spydata, range){
z = getSpyDataWithinRangeofGame(spydata, worldcup[[1,"Datetime"]], range)
gamerow = worldcup[1,]
for(colIndx in 1: ncol(gamerow)){
colvalue = worldcup[[1, colIndx]]
colname = colnames(worldcup)[colIndx]
z[colname] = rep(colvalue, times= nrow(z))
}
z["time.from.game"] = as.numeric(difftime(z$date, worldcup[[1,"Datetime"]],units = "secs"))
for(gameIndx in 2:nrow(worldcup)){
x = getSpyDataWithinRangeofGame(spydata, worldcup[[gameIndx,"Datetime"]], range)
gamerow = worldcup[gameIndx,]
for(colIndx in 1: ncol(gamerow)){
colvalue = worldcup[[gameIndx, colIndx]]
colname = colnames(worldcup)[colIndx]
x[colname] = rep(colvalue, times= nrow(x))
}
x["time.from.game"] = as.numeric(difftime(x$date, x$Datetime, units = "secs"))
z = union_all(z,x)
}
return(z)
}
Get Spy Data combined with Game Data for a single game
#Gives Spydata and Difference from the game time for each worldcup game
getSpyAndGameDataForOneGame = function(spydata,worldcup, game_index, range){
z = getSpyDataWithinRangeofGame(spydata, worldcup[[game_index,"Datetime"]], range)
for(colIndx in 1: ncol(worldcup[game_index,])){
colvalue = worldcup[[game_index, colIndx]]
colname = colnames(worldcup)[colIndx]
z[colname] = rep(colvalue, times= nrow(z))
}
z["time.from.game"] = as.numeric(difftime(z$date, rep(worldcup[[game_index,"Datetime"]], times = nrow(z)), units="secs"))
return(z)
}
Cleaning Data
#Update
spydata$date = as.POSIXct(spydata$date, format="%Y%m%d %H:%M:%S")
#Remove Rows containing NA's
cleaned_worldcupmatches = unique(worldcupmatches[!apply(is.na(worldcupmatches) | worldcupmatches == "", 1, all),])
#Convert Date and Time into POSIX EDT
cleaned_worldcupmatches$Datetime = as.POSIXct(cleaned_worldcupmatches$Datetime, format = "%e %b %Y - %R") - 60 * 60
#Filter Games on the Weekend
cleaned_worldcupmatches = filter(cleaned_worldcupmatches, wday(as.Date(Datetime)) != 7 & wday(as.Date(Datetime)) != 1)
#Filter Games that have no corresponding Data
cleaned_worldcupmatches = add_column(cleaned_worldcupmatches,"HasSpyData" = hasSpyDataWithinRangeOfGame(spydata, cleaned_worldcupmatches$Datetime, 3))
cleaned_worldcupmatches = filter(cleaned_worldcupmatches, cleaned_worldcupmatches$HasSpyData == TRUE)
cleaned_worldcupmatches
Get Spy Data
#Get Spy data within 3 hours of the Game For both World cups
allspydata2014 = getSpyAndGameDataWithinWorldcup(filter(cleaned_worldcupmatches, Year==2014), spydata, 3)
allspydata2010 = getSpyAndGameDataWithinWorldcup(filter(cleaned_worldcupmatches, Year==2010), spydata, 3)
Normalizing the average price
#Normalize the Data so that we can compare fairly the growth of stock price
max.2014 = max(allspydata2014$average)
max.2010 = max(allspydata2010$average)
min.2014 = min(allspydata2014$average)
min.2010 = min(allspydata2010$average)
difference.2014 = (max.2014) - (min.2014)
difference.2010 = (max.2010) - (min.2010)
normalized2014average = (allspydata2014$average-min.2014)/difference.2014
normalized2010average = (allspydata2010$average-min.2010)/difference.2010
allspydata2014 = add_column(allspydata2014, "normalized.average" = normalized2014average)
allspydata2010 = add_column(allspydata2010, "normalized.average" = normalized2010average)
allspydata = union_all(allspydata2014, allspydata2010)
allspydata
NA
Before we could perform any tests on the data sets, we first had to
take into account the stock price differences between the years 2010 and
2014. In order to normalize the stock price data, we had to split the
data into each year and normalize the prices within that year. The
method we chose to normalize the prices was subtracting the minimum
price for that year from each price. This value was then divided by the
difference between the maximum and minimum price for that year. Each
normalized price is a value between zero and one. When interpreting
these values, the closer the normalized value is to one, the closer the
price is to the maximum for that year. Similarly, the closer the value
is to zero, the closer the price is to the minimum for that year. By
normalizing the prices for each year, we created an even playing field
for price data, as they are all relative to the stock market climate in
their given year.
Exploring the Relationship of Time and Volume
Let us explore the Correlation between the Time form game and the
Price of the stock
Correlations
ggpairs(allspydata, columns = c("time.from.game", "average", "volume", "normalized.average"))

kable(cor(allspydata[, c(7,9,31,32)]))
|
|
volume
|
average
|
time.from.game
|
normalized.average
|
|
volume
|
1.0000000
|
-0.4039908
|
0.0334462
|
0.1264736
|
|
average
|
-0.4039908
|
1.0000000
|
0.2149680
|
-0.3961910
|
|
time.from.game
|
0.0334462
|
0.2149680
|
1.0000000
|
0.0158785
|
|
normalized.average
|
0.1264736
|
-0.3961910
|
0.0158785
|
1.0000000
|
After cleaning the data set, we computed the cross-correlations for
the variables: time from the game, volume of trades, average price, and
normalized average price. We were most interested in seeing how time
from game affected volume of trades since volume shows stock
productivity. We found that time from game had the highest correlation
with average price, the correlation was 0.215. We also found that the
correlation between time from game and volume was .033. These low values
make sense given the data we had access to. We did not have data for
commonly traded stocks by day traders. Nevertheless, we wanted to
regress with volume as the dependent variable and time from game as the
independent variable. After attempting multiple regression types,
nonlinear regression gave us the best fit.Â
Linear Regression
ggplot(allspydata) + geom_point(aes(time.from.game,normalized.average))

ggplot(allspydata, aes(time.from.game,log(volume))) + geom_point() + geom_smooth() + geom_vline(xintercept= 0, color = "red") + geom_vline(xintercept = 5400, color ="red")

The model we used for nonlinear regression is a Generalized Additive
Model, also known as a GAM. A GAM is made up of splines, splines are
smooth polynomial functions that cover a small range. These splines
replace the beta coefficients that we normally see in linear regression,
so that we can regress on nonlinear data. When we graph our nonlinear
model over the volume data, we see that there is a spike in volume of
trades 5000 seconds before the time of the game, which is about an hour
and a half before the game. After this spike, there is a gradual
increase once the game starts and the positive trend continues as the
game finishes.
Sample Games from a World Cup
set.seed(100)
samplesize = 10
worldcupmatches2014 = filter(cleaned_worldcupmatches, Year == 2014)
sampleworldcupgames = sample_n(worldcupmatches2014,size = samplesize)
game1 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 1, 3)
volumesp1 <- ggplot(game1, mapping = aes(x=date, y=log(volume))) + geom_point(aes(color =average)) + geom_vline(xintercept= sampleworldcupgames$Datetime[1]) + ggtitle("Volume over Time, Sample Game 1")
volumesp1

game2 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 2, 3)
volumesp2 <- ggplot(game2, mapping = aes(x=date, y=log(volume))) + geom_point(aes(color =average)) + geom_vline(xintercept= sampleworldcupgames$Datetime[2])+ ggtitle("Volume over Time, Sample Game 2")
volumesp2

#ERROR AGAIN WE DONT HAVE FULL DATA FOR THIS GAME
game3 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 3, 3)
volumesp3 <- ggplot(game3, mapping = aes(x=date, y=log(volume))) + geom_point(aes(color =average)) + geom_vline(xintercept= sampleworldcupgames$Datetime[3])+ ggtitle("Volume over Time, Sample Game 3")
volumesp3

game4 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 4, 3)
volumesp4 <- ggplot(game4, mapping = aes(x=date, y=log(volume))) + geom_point(aes(color =average)) + geom_vline(xintercept= sampleworldcupgames$Datetime[4])+ ggtitle("Volume over Time, Sample Game 4")
volumesp4

game5 <- getSpyAndGameDataForOneGame(spydata, sampleworldcupgames, 5, 3)
volumesp5 <- ggplot(game5, mapping = aes(x=date, y=log(volume))) + geom_point(aes(color =average)) + geom_vline(xintercept= sampleworldcupgames$Datetime[5])+ ggtitle("Volume over Time, Sample Game 5")
volumesp5

Price Scatter Plots
Using average price
pricesp1 <- ggplot(game1) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[1])+ ggtitle("Price over Time, Sample Game 1")
pricesp1

pricesp2 <- ggplot(game2) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[2])+ ggtitle("Price over Time, Sample Game 2")
pricesp2

#ISSUE BECAUSE WE DONT HAVE DATA FOR 16:00 and that is time of the game
pricesp3 <- ggplot(game3) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[3])+ ggtitle("Price over Time, Sample Game 3")
pricesp3

pricesp4 <- ggplot(game4) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[4])+ ggtitle("Price over Time, Sample Game 4")
pricesp4

pricesp5 <- ggplot(game5, aes(date)) + geom_point(aes(y=average, ), color ="red") + geom_vline(xintercept= sampleworldcupgames$Datetime[5])+ ggtitle("Price over Time, Sample Game 5")
pricesp5

We next looked at the volume of trading over a range of time from
five sample games. Using ggpoint, we plotted the scatter plot of the
market volume over a period of a few hours before and after the start of
the game, and we indicated the start time with a vertical line on the
graph. The values for volume are very large and varied, which makes the
graphs difficult to read. To make them more digestible, we instead used
the log of volume as the dependent variable, giving us smaller numbers.
We found that, in general, there is a slight dip in the volume around
the start time of the game. This agrees with findings from our research
that stock market activity drops durring the World Cup as more attention
is directed towards the games. We also used scatter plots to look at the
average price of stocks over a range of time around the start time of
sample games. As for the volume plots, we indicated the start time of
the game with a vertical line on the graph. The figures show that the
average price tends to drop just before the start of the game, and then
increase. These trends in price lead us to explore the times it would be
best to both buy and sell stocks.
Just USA Games
worldcupmatchesUSAhome = filter(cleaned_worldcupmatches, Home.Team.Name == "USA")
worldcupmatchesUSAaway = filter(cleaned_worldcupmatches, Away.Team.Name == "USA")
worldcupmatchesUSA <- union_all(worldcupmatchesUSAaway,worldcupmatchesUSAhome)
worldcupmatchesUSA
game1USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 1, 3)
volumesp1USA <- ggplot(game1USA) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[1])+ ggtitle("Volume over Time, USA Game 1, 2010")
volumesp1USA

game2USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 2, 3)
volumesp2USA <- ggplot(game2USA) + geom_point(mapping = aes(x=date, y=log(volume)), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[2])+ ggtitle("Volume over Time, USA Game 2, 2014")
volumesp2USA

game3USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 3, 3)
volumesp3USA <- ggplot(game3USA) + geom_point(mapping = aes(x=date, y=volume), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[3])+ ggtitle("Volume over Time, USA Game 2, 2010")
volumesp3USA

game4USA <- getSpyAndGameDataForOneGame(spydata, worldcupmatchesUSA, 4, 3)
volumesp4USA <- ggplot(game4USA) + geom_point(mapping = aes(x=date, y=volume), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[4])+ ggtitle("Volume over Time, USA Game 1, 2014")
volumesp4USA

pricesp4USA <- ggplot(game4USA) + geom_point(mapping = aes(x=date, y=average), color ="red") + geom_vline(xintercept= worldcupmatchesUSA$Datetime[4])+ ggtitle("Price over Time, USA Game 1, 2014")
pricesp4USA

Is there a way to make money during World Cup Games?
What time should you look to sell?
price_list = c()
time_list = c()
for (game in 1:nrow(cleaned_worldcupmatches)) {
price_game_data <- getSpyAndGameDataForOneGame(spydata, cleaned_worldcupmatches, game, 3)
highestdatapoint = price_game_data[which.max(price_game_data$average),]
highestpriceforgame <- highestdatapoint$average
time <- highestdatapoint$"time.from.game"
price_list = append(price_list, highestpriceforgame)
time_list = append(time_list, time)
}
optimal_selling.df <- data.frame("price" = price_list, "time" = time_list)
optimal_selling.df
Do THis for Optimal Buying time?
ggplot(optimal_selling.df) + geom_histogram(mapping = aes(x= time)) + ggtitle("How Often Best Selling Time is vs. Time From Game")

What time should you look to buy?
price_list = c()
time_list = c()
for (game in 1:nrow(cleaned_worldcupmatches)) {
price_game_data <- getSpyAndGameDataForOneGame(spydata, cleaned_worldcupmatches, game, 3)
lowestdatapoint = price_game_data[which.min(price_game_data$average),]
lowestpriceforgame <- lowestdatapoint$average
time <- lowestdatapoint$"time.from.game"
price_list = append(price_list, lowestpriceforgame)
time_list = append(time_list, time)
}
optimal_buying.df <- data.frame("price" = price_list, "time" = time_list)
ggplot(optimal_buying.df) + geom_histogram(mapping = aes(x= time)) + ggtitle("How Often Best Buying Time is vs. Time From Game")

Another idea we wanted to explore was the optimal buying and selling
times for SPY. The optimal buying time would be when the SPY price is
the lowest and the optimal selling time would be when the SPY price is
the highest. In order to find the optimal times from the game, we found
the maximum and minimum price of SPY during each game. From there, we
found the corresponding time from game for these maximum and minimum
price values. With this data, we created two histograms: one that
demonstrates the optimal buying times from a world cup game and another
that demonstrated the optimal selling times from a world cup game. The
histograms display the time from game on the x-axis and show the amount
of hames that have their optimal selling or buying time at that time
value. For the optimal selling histogram, there are peaks at 10,000
seconds and 5,000 seconds before the game. These two time values
correspond to around three hours before the game and one and a half
hours before the game, respectively. There were other outliers in the
histogram, but these two values seem to be the best times around a world
cup game to sell SPY stock, based on our data. For the optimal buying
histogram, there was a large peak around 10,000 seconds before the game,
which is three hours before the game. The histogram is skewed right, so
the times where the SPY price was the lowest was before the game. From
this histogram, it appears that the best time to buy SPY stock is three
hours before the start of a world cup game.Â
Does the importance of the game matter in the total amount of
trades?
allspydata$Stage[grepl("Group", allspydata$Stage, fixed = TRUE)] = "Group"
ggplot(allspydata, aes(log(volume), Stage, fill = Stage)) + geom_boxplot() + ggtitle("Log(Volume) vs. Stage Of Game")

allspydata$Stage[grepl("Group", allspydata$Stage, fixed = TRUE)] = "Group"
ggplot(allspydata, aes(log(volume), Stage, fill = Stage)) + geom_boxplot() + ggtitle("Log(Volume) vs. Stage Of Game")
LS0tCnRpdGxlOiAiTUFUSCAzMTggRmluYWwgUHJvamVjdCIKb3V0cHV0OiBodG1sX25vdGVib29rCi0tLQoKIyBNQVRIIDMxOCBGaW5hbCBQcm9qZWN0OiBUaGUgRWZmZWN0IG9mIFdvcmxkIEN1cCBvbiBTdG9jayBQcmljZSBhbmQgVHJhZGluZyBBY3Rpdml0eQoKYGBge3J9CmxpYnJhcnkodGlkeXZlcnNlKQpsaWJyYXJ5KGRwbHlyKQpsaWJyYXJ5KE1BU1MpCmxpYnJhcnkobHVicmlkYXRlKQpsaWJyYXJ5KHN0cmluZ3IpCmxpYnJhcnkoR0dhbGx5KQpsaWJyYXJ5KGtuaXRyKQpsaWJyYXJ5KGthYmxlRXh0cmEpCmxpYnJhcnkodGlkeXF1YW50KQpgYGAKCiMgSW50cm9kdWN0aW9uCgpPdXIgZ29hbCBpbiB0aGlzIHByb2plY3Qgd2FzIHRvIGV4cGxvcmUgdGhlIGVmZmVjdCB0aGUgRklGQSBXb3JsZCBDdXAgaGFzIG9uIHRoZSBzdG9jayBtYXJrZXQuIEluIHJlc2VhcmNoaW5nIHRvIHByZXBhcmUsIHdlIGZvdW5kIHRoYXQgdGhlIFdvcmxkIEN1cCBoYXMgYSBnZW5lcmFsbHkgbmVnYXRpdmUgaW1wYWN0IG9uIHRoZSBtYXJrZXQuIEFjY29yZGluZyB0byBhbiBhcnRpY2xlIGZyb20gTWFya2V0V2F0Y2gsIGEgY291bnRyeVwncyBhdmVyYWdlIG1hcmtldCByZXR1cm4gc2lnbmlmaWNhbnRseSBkcm9wcyBhZnRlciB0aGVpciB0ZWFtIGlzIGVsaW1pbmF0ZWQgZnJvbSB0aGUgQ3VwLiBUaGUgaW52ZXJzZSBjYW5cJ3QgYmUgc2FpZCBmb3IgdGVhbSB3aW5zLCB3aGljaCBsZWFkcyB0byB0aGUgb3ZlcmFsbCBtYXJrZXQgZGVjcmVhc2luZy4gT3VyIGludGVyZXN0IHdhcyB0byBpbnZlc3RpZ2F0ZSB0aGUgbWFya2V0IHRyZW5kcywgc3BlY2lmaWNhbGx5IHJlZ2FyZGluZyB0aGUgUyZQIDUwMCwgaW4gcmVsYXRpb24gdG8gdGhlIHRpbWVzIG9mIFdvcmxkIEN1cCBnYW1lcy7CoAoKIyMgRXhwbG9yYXRpb24KCmBgYHtyfQpjYW5kbGVTdGlja19wbG90PC1mdW5jdGlvbihzeW1ib2wsZnJvbSx0byl7CiAgdHFfZ2V0KHN5bWJvbCwKICAgICAgICBmcm9tID0gZnJvbSwKICAgICAgICB0byA9IHRvLAogICAgICAgIHdhcm5pbmdzID0gRkFMU0UpICU+JSBtdXRhdGUoZ3JlZW5SZWQ9aWZlbHNlKG9wZW4tY2xvc2U+MCwKICAgICAgICAgICAgICAgICAgICAgICAgICAgIlJlZCIsCiAgICAgICAgICAgICAgICAgICAgICAgICAgICJHcmVlbiIpKSAlPiUKICAgIGdncGxvdCgpKwogICAgZ2VvbV9zZWdtZW50KGFlcyh4ID0gZGF0ZSwKICAgICAgICAgICAgICAgICAgICAgeGVuZD1kYXRlLAogICAgICAgICAgICAgICAgICAgICB5ID1vcGVuLAogICAgICAgICAgICAgICAgICAgICB5ZW5kID1jbG9zZSwKICAgICAgICAgICAgICAgICAgICAgY29sb3VyPWdyZWVuUmVkKSwKICAgICAgICAgICAgICAgICBzaXplPTMpKwogICAgdGhlbWVfdHEoKSsKICAgIGdlb21fc2VnbWVudChhZXMoeCA9IGRhdGUsCiAgICAgICAgICAgICAgICAgICAgIHhlbmQ9ZGF0ZSwKICAgICAgICAgICAgICAgICAgICAgeSA9aGlnaCwKICAgICAgICAgICAgICAgICAgICAgeWVuZCA9bG93LAogICAgICAgICAgICAgICAgICAgICBjb2xvdXI9Z3JlZW5SZWQpKSsKICAgIHNjYWxlX2NvbG9yX21hbnVhbCh2YWx1ZXM9YygiRm9yZXN0IEdyZWVuIiwiUmVkIikpKwogICAgZ2d0aXRsZShwYXN0ZTAoc3ltYm9sLCIgKCIsZnJvbSwiIC0gIix0bywiKSIpKSsKICAgIHRoZW1lKGxlZ2VuZC5wb3NpdGlvbiA9Im5vbmUiLAogICAgICAgICAgYXhpcy50aXRsZS55ID0gZWxlbWVudF9ibGFuaygpLAogICAgICAgICAgYXhpcy50aXRsZS54PWVsZW1lbnRfYmxhbmsoKSwKICAgICAgICAgIGF4aXMudGV4dC54ID0gZWxlbWVudF90ZXh0KGFuZ2xlID0gOTAsIHZqdXN0ID0gMC41LCBoanVzdD0xKSwKICAgICAgICAgIHBsb3QudGl0bGU9IGVsZW1lbnRfdGV4dChoanVzdD0wLjUpKQp9CgpgYGAKCmBgYHtyfQpjYW5kbGVTdGlja19wbG90KCJTUFkiLCBmcm9tID0gJzIwMDItMDUtMzEnLCB0byA9ICcyMDAyLTA2LTMwJykKY2FuZGxlU3RpY2tfcGxvdCgiU1BZIiwgZnJvbSA9ICcyMDA2LTA2LTA5JywgdG8gPSAnMjAwNi0wNy0wOScpCmNhbmRsZVN0aWNrX3Bsb3QoIlNQWSIsIGZyb20gPSAnMjAxMC0wNi0xMScsdG8gPSAnMjAxMC0wNy0xMScpCmNhbmRsZVN0aWNrX3Bsb3QoIlNQWSIsIGZyb20gPSAnMjAxNC0wNi0xMicsdG8gPSAnMjAxNC0wNy0xMycpCmBgYAoKIyBMb2FkIERhdGEKCmBgYHtyfQpzcHlkYXRhID0gYXNfdGliYmxlKHJlYWQuY3N2KCIxX21pbl9TUFlfMjAwOC0yMDIxLmNzdiIpKQpgYGAKCmBgYHtyfQp3b3JsZGN1cG1hdGNoZXMgPSBhc190aWJibGUocmVhZC5jc3YoIldvcmxkQ3VwTWF0Y2hlcy5jc3YiKSkKYGBgCgpXZSB3ZXJlIGludGVyZXN0ZWQgaW4gbG9va2luZyBhdCB0aGUgZ2VuZXJhbCBwcmljZSBvZiB0aGUgbWFya2V0IGR1cmluZyB0aGUgd29ybGQgY3VwLCB0byBjb25maXJtIGlmIG91ciBkYXRhIHNob3dzIHRoZSBwcm9wb3NlZCB0cmVuZCBvZiBkZWNyZWFzZWQgcHJpY2UgZHVyaW5nIHRoZSBXb3JsZCBDdXDCoCB3ZSBmb3VuZCBpbiBvdXIgcmVzZWFyY2guIFRvIGRvIHRoaXMgd2UgdXNlZCBhIGdyYXBoaW5nIG1ldGhvZCBjYWxsZWQgY2FuZGxlc3RpY2tzIHBsb3RzLiBUaGVzZSBwbG90cyBzaG93IHRoZSBhdmVyYWdlIGFuZCB2YXJpYXRpb24gb2YgdGhlIHByaWNlIG92ZXIgYSBnaXZlbiBtb250aC4gRWFjaCBwbG90IHNwYW5uZWQgdGhlIG1vbnRoIG9mIHRoZSBXb3JsZCBDdXAgZm9yIHRoZSB5ZWFycyAyMDAyLCAyMDA2LCAyMDEwLCAyMDE0LiBCb3RoIHRoZSBncmFwaCBmb3IgMjAwMiBhbmQgMjAxMCBkaXNwbGF5IGEgZ2VuZXJhbGx5IGRlY3JlYXNpbmcgdHJlbmQgdGhyb3VnaG91dCB0aGUgbW9udGguIEhvd2V2ZXIsIHRoZSAyMDA2IGFuZCAyMDE0IGdyYXBocyBpbnN0ZWFkIHNob3cgYSBnZW5lcmFsIGluY3JlYXNlIGluIHByaWNlIG92ZXIgdGltZS4gVG8gYmV0dGVyIHVuZGVyc3RhbmQgdHJlbmRzIGluIHRoZSBkYXRhLCB3ZSB0aGVuIGxvb2tlZCBjbG9zZXIgYXQgaW5mb3JtYXRpb24gZnJvbSBzaW5ndWxhciBnYW1lcy7CoAoKXApcCgojIEhlbHBlciBGdW5jdGlvbnMKCiMjIEdldCBPbmx5IFNweSBEYXRhIGZvciBhIFNwZWNpZmljIEdhbWUKCmBgYHtyfQojQ2xlYW4gU3B5RGF0YSBQZXIgR2FtZQpnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUgPSBmdW5jdGlvbihzcHlkYXRhLGdhbWVfZGF0ZSxyYW5nZSl7CiAgcmFuZ2VJblNlY29uZHMgPSA2MCAqIDYwICogcmFuZ2UKICByZXR1cm4oZmlsdGVyKHNweWRhdGEsIChkYXRlID49IGdhbWVfZGF0ZSAtIHJhbmdlSW5TZWNvbmRzKSAmIChkYXRlIDw9IGdhbWVfZGF0ZSArIHJhbmdlSW5TZWNvbmRzKSkpCn0KYGBgCgojIyBDaGVjayBpZiB0aGVyZSBpcyBTcHkgZGF0YSBmb3IgYSBnYW1lCgpgYGB7cn0KaGFzU3B5RGF0YVdpdGhpblJhbmdlT2ZHYW1lID0gZnVuY3Rpb24oc3B5ZGF0YSwgZ2FtZV9kYXRlcywgcmFuZ2UpewogIGxpc3QgPSBjKCkKICBmb3IoZ2FtZV9kYXRlIGluIDE6bGVuZ3RoKGdhbWVfZGF0ZXMpKXsKICAgIGxpc3QgPSBhcHBlbmQobGlzdCwgbnJvdyhnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUoc3B5ZGF0YSwgZ2FtZV9kYXRlID0gZ2FtZV9kYXRlc1tnYW1lX2RhdGVdLCByYW5nZSkpICE9IDApCiAgfQogIHJldHVybihsaXN0KQp9CmBgYAoKIyMgR2V0IFNweSBEYXRhIGNvbWJpbmVkIHdpdGggR2FtZSBEYXRhIGZvciBhIHNldCBvZiBHYW1lcwoKYGBge3J9CiNDbGVhbiBTcHlkYXRhIFBlciBXb3JsZGN1cCBSZXR1cm5zIGEgc2V0IG9mIHNweWRhdGEgd2l0aCB0aGVpciBjb3JyZXNwb25kaW5nIGdhbWUgZGF0YQpnZXRTcHlBbmRHYW1lRGF0YVdpdGhpbldvcmxkY3VwID0gZnVuY3Rpb24od29ybGRjdXAsIHNweWRhdGEsIHJhbmdlKXsKICB6ID0gZ2V0U3B5RGF0YVdpdGhpblJhbmdlb2ZHYW1lKHNweWRhdGEsIHdvcmxkY3VwW1sxLCJEYXRldGltZSJdXSwgcmFuZ2UpCiAgZ2FtZXJvdyA9IHdvcmxkY3VwWzEsXQogIGZvcihjb2xJbmR4IGluIDE6IG5jb2woZ2FtZXJvdykpewogICAgICBjb2x2YWx1ZSA9IHdvcmxkY3VwW1sxLCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB6W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh6KSkKICB9CiAgelsidGltZS5mcm9tLmdhbWUiXSA9IGFzLm51bWVyaWMoZGlmZnRpbWUoeiRkYXRlLCB3b3JsZGN1cFtbMSwiRGF0ZXRpbWUiXV0sdW5pdHMgPSAic2VjcyIpKQogIGZvcihnYW1lSW5keCBpbiAyOm5yb3cod29ybGRjdXApKXsKICAgeCA9IGdldFNweURhdGFXaXRoaW5SYW5nZW9mR2FtZShzcHlkYXRhLCB3b3JsZGN1cFtbZ2FtZUluZHgsIkRhdGV0aW1lIl1dLCByYW5nZSkKICAgZ2FtZXJvdyA9IHdvcmxkY3VwW2dhbWVJbmR4LF0KICAgZm9yKGNvbEluZHggaW4gMTogbmNvbChnYW1lcm93KSl7CiAgICAgIGNvbHZhbHVlID0gd29ybGRjdXBbW2dhbWVJbmR4LCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB4W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh4KSkKICAgfQogICB4WyJ0aW1lLmZyb20uZ2FtZSJdID0gYXMubnVtZXJpYyhkaWZmdGltZSh4JGRhdGUsIHgkRGF0ZXRpbWUsIHVuaXRzID0gInNlY3MiKSkKICAKICAgeiA9IHVuaW9uX2FsbCh6LHgpCiAgfQogIHJldHVybih6KQp9CmBgYAoKIyMgR2V0IFNweSBEYXRhIGNvbWJpbmVkIHdpdGggR2FtZSBEYXRhIGZvciBhIHNpbmdsZSBnYW1lCgpgYGB7cn0KI0dpdmVzIFNweWRhdGEgYW5kIERpZmZlcmVuY2UgZnJvbSB0aGUgZ2FtZSB0aW1lIGZvciBlYWNoIHdvcmxkY3VwIGdhbWUKZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lID0gZnVuY3Rpb24oc3B5ZGF0YSx3b3JsZGN1cCwgZ2FtZV9pbmRleCwgcmFuZ2UpewogIHogPSBnZXRTcHlEYXRhV2l0aGluUmFuZ2VvZkdhbWUoc3B5ZGF0YSwgd29ybGRjdXBbW2dhbWVfaW5kZXgsIkRhdGV0aW1lIl1dLCByYW5nZSkKICBmb3IoY29sSW5keCBpbiAxOiBuY29sKHdvcmxkY3VwW2dhbWVfaW5kZXgsXSkpewogICAgICBjb2x2YWx1ZSA9IHdvcmxkY3VwW1tnYW1lX2luZGV4LCBjb2xJbmR4XV0KICAgICAgY29sbmFtZSA9IGNvbG5hbWVzKHdvcmxkY3VwKVtjb2xJbmR4XQogICAgICB6W2NvbG5hbWVdID0gcmVwKGNvbHZhbHVlLCB0aW1lcz0gbnJvdyh6KSkKICB9CiAgelsidGltZS5mcm9tLmdhbWUiXSA9IGFzLm51bWVyaWMoZGlmZnRpbWUoeiRkYXRlLCByZXAod29ybGRjdXBbW2dhbWVfaW5kZXgsIkRhdGV0aW1lIl1dLCB0aW1lcyA9IG5yb3coeikpLCB1bml0cz0ic2VjcyIpKQogIHJldHVybih6KQp9CmBgYAoKIyBDbGVhbmluZyBEYXRhCgpgYGB7cn0KI1VwZGF0ZSAKc3B5ZGF0YSRkYXRlID0gYXMuUE9TSVhjdChzcHlkYXRhJGRhdGUsIGZvcm1hdD0iJVklbSVkICVIOiVNOiVTIikKCiNSZW1vdmUgUm93cyBjb250YWluaW5nIE5BJ3MKY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMgPSB1bmlxdWUod29ybGRjdXBtYXRjaGVzWyFhcHBseShpcy5uYSh3b3JsZGN1cG1hdGNoZXMpIHwgd29ybGRjdXBtYXRjaGVzID09ICIiLCAxLCBhbGwpLF0pCgojQ29udmVydCBEYXRlIGFuZCBUaW1lIGludG8gUE9TSVggRURUIApjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcyREYXRldGltZSA9IGFzLlBPU0lYY3QoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMkRGF0ZXRpbWUsIGZvcm1hdCA9ICIlZSAlYiAlWSAtICVSIikgLSA2MCAqIDYwCgojRmlsdGVyIEdhbWVzIG9uIHRoZSBXZWVrZW5kCmNsZWFuZWRfd29ybGRjdXBtYXRjaGVzID0gZmlsdGVyKGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzLCB3ZGF5KGFzLkRhdGUoRGF0ZXRpbWUpKSAhPSA3ICYgd2RheShhcy5EYXRlKERhdGV0aW1lKSkgIT0gMSkKCiNGaWx0ZXIgR2FtZXMgdGhhdCBoYXZlIG5vIGNvcnJlc3BvbmRpbmcgRGF0YQpjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcyA9IGFkZF9jb2x1bW4oY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIkhhc1NweURhdGEiID0gaGFzU3B5RGF0YVdpdGhpblJhbmdlT2ZHYW1lKHNweWRhdGEsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzJERhdGV0aW1lLCAzKSkKY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMgPSBmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIGNsZWFuZWRfd29ybGRjdXBtYXRjaGVzJEhhc1NweURhdGEgPT0gVFJVRSkKCmNsZWFuZWRfd29ybGRjdXBtYXRjaGVzCmBgYAoKIyMgR2V0IFNweSBEYXRhCgpgYGB7cn0KI0dldCBTcHkgZGF0YSB3aXRoaW4gMyBob3VycyBvZiB0aGUgR2FtZSBGb3IgYm90aCBXb3JsZCBjdXBzCmFsbHNweWRhdGEyMDE0ID0gZ2V0U3B5QW5kR2FtZURhdGFXaXRoaW5Xb3JsZGN1cChmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIFllYXI9PTIwMTQpLCBzcHlkYXRhLCAzKQoKYWxsc3B5ZGF0YTIwMTAgPSBnZXRTcHlBbmRHYW1lRGF0YVdpdGhpbldvcmxkY3VwKGZpbHRlcihjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgWWVhcj09MjAxMCksIHNweWRhdGEsIDMpCgpgYGAKCiMjIE5vcm1hbGl6aW5nIHRoZSBhdmVyYWdlIHByaWNlCgpgYGB7cn0KI05vcm1hbGl6ZSB0aGUgRGF0YSBzbyB0aGF0IHdlIGNhbiBjb21wYXJlIGZhaXJseSB0aGUgZ3Jvd3RoIG9mIHN0b2NrIHByaWNlCm1heC4yMDE0ID0gbWF4KGFsbHNweWRhdGEyMDE0JGF2ZXJhZ2UpCm1heC4yMDEwID0gbWF4KGFsbHNweWRhdGEyMDEwJGF2ZXJhZ2UpCgoKbWluLjIwMTQgPSBtaW4oYWxsc3B5ZGF0YTIwMTQkYXZlcmFnZSkKbWluLjIwMTAgPSBtaW4oYWxsc3B5ZGF0YTIwMTAkYXZlcmFnZSkKCmRpZmZlcmVuY2UuMjAxNCA9IChtYXguMjAxNCkgLSAobWluLjIwMTQpCmRpZmZlcmVuY2UuMjAxMCA9IChtYXguMjAxMCkgLSAobWluLjIwMTApCm5vcm1hbGl6ZWQyMDE0YXZlcmFnZSA9IChhbGxzcHlkYXRhMjAxNCRhdmVyYWdlLW1pbi4yMDE0KS9kaWZmZXJlbmNlLjIwMTQKbm9ybWFsaXplZDIwMTBhdmVyYWdlID0gKGFsbHNweWRhdGEyMDEwJGF2ZXJhZ2UtbWluLjIwMTApL2RpZmZlcmVuY2UuMjAxMAoKCmFsbHNweWRhdGEyMDE0ID0gYWRkX2NvbHVtbihhbGxzcHlkYXRhMjAxNCwgIm5vcm1hbGl6ZWQuYXZlcmFnZSIgPSBub3JtYWxpemVkMjAxNGF2ZXJhZ2UpCmFsbHNweWRhdGEyMDEwID0gYWRkX2NvbHVtbihhbGxzcHlkYXRhMjAxMCwgIm5vcm1hbGl6ZWQuYXZlcmFnZSIgPSBub3JtYWxpemVkMjAxMGF2ZXJhZ2UpCgphbGxzcHlkYXRhID0gdW5pb25fYWxsKGFsbHNweWRhdGEyMDE0LCBhbGxzcHlkYXRhMjAxMCkKCmFsbHNweWRhdGEKYGBgCgpCZWZvcmUgd2UgY291bGQgcGVyZm9ybSBhbnkgdGVzdHMgb24gdGhlIGRhdGEgc2V0cywgd2UgZmlyc3QgaGFkIHRvIHRha2UgaW50byBhY2NvdW50IHRoZSBzdG9jayBwcmljZSBkaWZmZXJlbmNlcyBiZXR3ZWVuIHRoZSB5ZWFycyAyMDEwIGFuZCAyMDE0LiBJbiBvcmRlciB0byBub3JtYWxpemUgdGhlIHN0b2NrIHByaWNlIGRhdGEsIHdlIGhhZCB0byBzcGxpdCB0aGUgZGF0YSBpbnRvIGVhY2ggeWVhciBhbmQgbm9ybWFsaXplIHRoZSBwcmljZXMgd2l0aGluIHRoYXQgeWVhci4gVGhlIG1ldGhvZCB3ZSBjaG9zZSB0byBub3JtYWxpemUgdGhlIHByaWNlcyB3YXMgc3VidHJhY3RpbmcgdGhlIG1pbmltdW0gcHJpY2UgZm9yIHRoYXQgeWVhciBmcm9tIGVhY2ggcHJpY2UuIFRoaXMgdmFsdWUgd2FzIHRoZW4gZGl2aWRlZCBieSB0aGUgZGlmZmVyZW5jZSBiZXR3ZWVuIHRoZSBtYXhpbXVtIGFuZCBtaW5pbXVtIHByaWNlIGZvciB0aGF0IHllYXIuIEVhY2ggbm9ybWFsaXplZCBwcmljZSBpcyBhIHZhbHVlIGJldHdlZW4gemVybyBhbmQgb25lLiBXaGVuIGludGVycHJldGluZyB0aGVzZSB2YWx1ZXMsIHRoZSBjbG9zZXIgdGhlIG5vcm1hbGl6ZWQgdmFsdWUgaXMgdG8gb25lLCB0aGUgY2xvc2VyIHRoZSBwcmljZSBpcyB0byB0aGUgbWF4aW11bSBmb3IgdGhhdCB5ZWFyLiBTaW1pbGFybHksIHRoZSBjbG9zZXIgdGhlIHZhbHVlIGlzIHRvIHplcm8sIHRoZSBjbG9zZXIgdGhlIHByaWNlIGlzIHRvIHRoZSBtaW5pbXVtIGZvciB0aGF0IHllYXIuIEJ5IG5vcm1hbGl6aW5nIHRoZSBwcmljZXMgZm9yIGVhY2ggeWVhciwgd2UgY3JlYXRlZCBhbiBldmVuIHBsYXlpbmcgZmllbGQgZm9yIHByaWNlIGRhdGEsIGFzIHRoZXkgYXJlIGFsbCByZWxhdGl2ZSB0byB0aGUgc3RvY2sgbWFya2V0IGNsaW1hdGUgaW4gdGhlaXIgZ2l2ZW4geWVhci4KCiMgRXhwbG9yaW5nIHRoZSBSZWxhdGlvbnNoaXAgb2YgVGltZSBhbmQgVm9sdW1lCgpMZXQgdXMgZXhwbG9yZSB0aGUgQ29ycmVsYXRpb24gYmV0d2VlbiB0aGUgVGltZSBmb3JtIGdhbWUgYW5kIHRoZSBQcmljZSBvZiB0aGUgc3RvY2sKCiMjIENvcnJlbGF0aW9ucwoKYGBge3J9CmdncGFpcnMoYWxsc3B5ZGF0YSwgY29sdW1ucyA9IGMoInRpbWUuZnJvbS5nYW1lIiwgImF2ZXJhZ2UiLCAidm9sdW1lIiwgIm5vcm1hbGl6ZWQuYXZlcmFnZSIpKQpgYGAKCmBgYHtyfQprYWJsZShjb3IoYWxsc3B5ZGF0YVssIGMoNyw5LDMxLDMyKV0pKQpgYGAKCkFmdGVyIGNsZWFuaW5nIHRoZSBkYXRhIHNldCwgd2UgY29tcHV0ZWQgdGhlIGNyb3NzLWNvcnJlbGF0aW9ucyBmb3IgdGhlIHZhcmlhYmxlczogdGltZSBmcm9tIHRoZSBnYW1lLCB2b2x1bWUgb2YgdHJhZGVzLCBhdmVyYWdlIHByaWNlLCBhbmQgbm9ybWFsaXplZCBhdmVyYWdlIHByaWNlLiBXZSB3ZXJlIG1vc3QgaW50ZXJlc3RlZCBpbiBzZWVpbmcgaG93IHRpbWUgZnJvbSBnYW1lIGFmZmVjdGVkIHZvbHVtZSBvZiB0cmFkZXMgc2luY2Ugdm9sdW1lIHNob3dzIHN0b2NrIHByb2R1Y3Rpdml0eS4gV2UgZm91bmQgdGhhdCB0aW1lIGZyb20gZ2FtZSBoYWQgdGhlIGhpZ2hlc3QgY29ycmVsYXRpb24gd2l0aCBhdmVyYWdlIHByaWNlLCB0aGUgY29ycmVsYXRpb24gd2FzIDAuMjE1LiBXZSBhbHNvIGZvdW5kIHRoYXQgdGhlIGNvcnJlbGF0aW9uIGJldHdlZW4gdGltZSBmcm9tIGdhbWUgYW5kIHZvbHVtZSB3YXMgLjAzMy4gVGhlc2UgbG93IHZhbHVlcyBtYWtlIHNlbnNlIGdpdmVuIHRoZSBkYXRhIHdlIGhhZCBhY2Nlc3MgdG8uIFdlIGRpZCBub3QgaGF2ZSBkYXRhIGZvciBjb21tb25seSB0cmFkZWQgc3RvY2tzIGJ5IGRheSB0cmFkZXJzLiBOZXZlcnRoZWxlc3MsIHdlIHdhbnRlZCB0byByZWdyZXNzIHdpdGggdm9sdW1lIGFzIHRoZSBkZXBlbmRlbnQgdmFyaWFibGUgYW5kIHRpbWUgZnJvbSBnYW1lIGFzIHRoZSBpbmRlcGVuZGVudCB2YXJpYWJsZS4gQWZ0ZXIgYXR0ZW1wdGluZyBtdWx0aXBsZSByZWdyZXNzaW9uIHR5cGVzLCBub25saW5lYXIgcmVncmVzc2lvbiBnYXZlIHVzIHRoZSBiZXN0IGZpdC7CoAoKIyMgTGluZWFyIFJlZ3Jlc3Npb24KCmBgYHtyfQpnZ3Bsb3QoYWxsc3B5ZGF0YSkgKyBnZW9tX3BvaW50KGFlcyh0aW1lLmZyb20uZ2FtZSxub3JtYWxpemVkLmF2ZXJhZ2UpKQpgYGAKCmBgYHtyfQpnZ3Bsb3QoYWxsc3B5ZGF0YSwgYWVzKHRpbWUuZnJvbS5nYW1lLGxvZyh2b2x1bWUpKSkgKyBnZW9tX3BvaW50KCkgKyBnZW9tX3Ntb290aCgpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSAwLCBjb2xvciA9ICJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdCA9IDU0MDAsIGNvbG9yID0icmVkIikKCmBgYAoKVGhlIG1vZGVsIHdlIHVzZWQgZm9yIG5vbmxpbmVhciByZWdyZXNzaW9uIGlzIGEgR2VuZXJhbGl6ZWQgQWRkaXRpdmUgTW9kZWwsIGFsc28ga25vd24gYXMgYSBHQU0uIEEgR0FNIGlzIG1hZGUgdXAgb2Ygc3BsaW5lcywgc3BsaW5lcyBhcmUgc21vb3RoIHBvbHlub21pYWwgZnVuY3Rpb25zIHRoYXQgY292ZXIgYSBzbWFsbCByYW5nZS4gVGhlc2Ugc3BsaW5lcyByZXBsYWNlIHRoZSBiZXRhIGNvZWZmaWNpZW50cyB0aGF0IHdlIG5vcm1hbGx5IHNlZSBpbiBsaW5lYXIgcmVncmVzc2lvbiwgc28gdGhhdCB3ZSBjYW4gcmVncmVzcyBvbiBub25saW5lYXIgZGF0YS4gV2hlbiB3ZSBncmFwaCBvdXIgbm9ubGluZWFyIG1vZGVsIG92ZXIgdGhlIHZvbHVtZSBkYXRhLCB3ZSBzZWUgdGhhdCB0aGVyZSBpcyBhIHNwaWtlIGluIHZvbHVtZSBvZiB0cmFkZXMgNTAwMCBzZWNvbmRzIGJlZm9yZSB0aGUgdGltZSBvZiB0aGUgZ2FtZSwgd2hpY2ggaXMgYWJvdXQgYW4gaG91ciBhbmQgYSBoYWxmIGJlZm9yZSB0aGUgZ2FtZS4gQWZ0ZXIgdGhpcyBzcGlrZSwgdGhlcmUgaXMgYSBncmFkdWFsIGluY3JlYXNlIG9uY2UgdGhlIGdhbWUgc3RhcnRzIGFuZCB0aGUgcG9zaXRpdmUgdHJlbmQgY29udGludWVzIGFzIHRoZSBnYW1lIGZpbmlzaGVzLgoKXApcCgojIFNhbXBsZSBHYW1lcyBmcm9tIGEgV29ybGQgQ3VwCgpgYGB7cn0Kc2V0LnNlZWQoMTAwKSAKc2FtcGxlc2l6ZSA9IDEwCndvcmxkY3VwbWF0Y2hlczIwMTQgPSBmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIFllYXIgPT0gMjAxNCkKc2FtcGxld29ybGRjdXBnYW1lcyA9IHNhbXBsZV9uKHdvcmxkY3VwbWF0Y2hlczIwMTQsc2l6ZSA9IHNhbXBsZXNpemUpCmBgYAoKYGBge3J9CmdhbWUxIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBzYW1wbGV3b3JsZGN1cGdhbWVzLCAxLCAzKQp2b2x1bWVzcDEgPC0gZ2dwbG90KGdhbWUxLCBtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSkpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPWF2ZXJhZ2UpKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVsxXSkgKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBTYW1wbGUgR2FtZSAxIikKdm9sdW1lc3AxCmBgYAoKYGBge3J9CmdhbWUyIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBzYW1wbGV3b3JsZGN1cGdhbWVzLCAyLCAzKQp2b2x1bWVzcDIgPC0gZ2dwbG90KGdhbWUyLCBtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSkpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPWF2ZXJhZ2UpKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVsyXSkrIGdndGl0bGUoIlZvbHVtZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDIiKQp2b2x1bWVzcDIKI0VSUk9SIEFHQUlOIFdFIERPTlQgSEFWRSBGVUxMIERBVEEgRk9SIFRISVMgR0FNRQpgYGAKCmBgYHtyfQpnYW1lMyA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgc2FtcGxld29ybGRjdXBnYW1lcywgMywgMykKdm9sdW1lc3AzIDwtIGdncGxvdChnYW1lMywgbWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9bG9nKHZvbHVtZSkpKSArIGdlb21fcG9pbnQoYWVzKGNvbG9yID1hdmVyYWdlKSkgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHNhbXBsZXdvcmxkY3VwZ2FtZXMkRGF0ZXRpbWVbM10pKyBnZ3RpdGxlKCJWb2x1bWUgb3ZlciBUaW1lLCBTYW1wbGUgR2FtZSAzIikKdm9sdW1lc3AzCmBgYAoKYGBge3J9CmdhbWU0IDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBzYW1wbGV3b3JsZGN1cGdhbWVzLCA0LCAzKQp2b2x1bWVzcDQgPC0gZ2dwbG90KGdhbWU0LCBtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSkpICsgZ2VvbV9wb2ludChhZXMoY29sb3IgPWF2ZXJhZ2UpKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVs0XSkrIGdndGl0bGUoIlZvbHVtZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDQiKQp2b2x1bWVzcDQKYGBgCgpgYGB7cn0KZ2FtZTUgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIHNhbXBsZXdvcmxkY3VwZ2FtZXMsIDUsIDMpCnZvbHVtZXNwNSA8LSBnZ3Bsb3QoZ2FtZTUsIG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWxvZyh2b2x1bWUpKSkgKyBnZW9tX3BvaW50KGFlcyhjb2xvciA9YXZlcmFnZSkpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSBzYW1wbGV3b3JsZGN1cGdhbWVzJERhdGV0aW1lWzVdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNSIpCnZvbHVtZXNwNQpgYGAKCiMjIFByaWNlIFNjYXR0ZXIgUGxvdHMKClVzaW5nIGF2ZXJhZ2UgcHJpY2UKCmBgYHtyfQpwcmljZXNwMSA8LSBnZ3Bsb3QoZ2FtZTEpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1hdmVyYWdlKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVsxXSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgMSIpCnByaWNlc3AxCmBgYAoKYGBge3J9CnByaWNlc3AyIDwtIGdncGxvdChnYW1lMikgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWF2ZXJhZ2UpLCBjb2xvciA9InJlZCIpICsgZ2VvbV92bGluZSh4aW50ZXJjZXB0PSBzYW1wbGV3b3JsZGN1cGdhbWVzJERhdGV0aW1lWzJdKSsgZ2d0aXRsZSgiUHJpY2Ugb3ZlciBUaW1lLCBTYW1wbGUgR2FtZSAyIikKcHJpY2VzcDIKI0lTU1VFIEJFQ0FVU0UgV0UgRE9OVCBIQVZFIERBVEEgRk9SIDE2OjAwIGFuZCB0aGF0IGlzIHRpbWUgb2YgdGhlIGdhbWUKYGBgCgpgYGB7cn0KcHJpY2VzcDMgPC0gZ2dwbG90KGdhbWUzKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9YXZlcmFnZSksIGNvbG9yID0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHNhbXBsZXdvcmxkY3VwZ2FtZXMkRGF0ZXRpbWVbM10pKyBnZ3RpdGxlKCJQcmljZSBvdmVyIFRpbWUsIFNhbXBsZSBHYW1lIDMiKQpwcmljZXNwMwpgYGAKCmBgYHtyfQpwcmljZXNwNCA8LSBnZ3Bsb3QoZ2FtZTQpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1hdmVyYWdlKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVs0XSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNCIpCnByaWNlc3A0CmBgYAoKYGBge3J9CnByaWNlc3A1IDwtIGdncGxvdChnYW1lNSwgYWVzKGRhdGUpKSArIGdlb21fcG9pbnQoYWVzKHk9YXZlcmFnZSwgKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gc2FtcGxld29ybGRjdXBnYW1lcyREYXRldGltZVs1XSkrIGdndGl0bGUoIlByaWNlIG92ZXIgVGltZSwgU2FtcGxlIEdhbWUgNSIpCnByaWNlc3A1CmBgYAoKV2UgbmV4dCBsb29rZWQgYXQgdGhlIHZvbHVtZSBvZiB0cmFkaW5nIG92ZXIgYSByYW5nZSBvZiB0aW1lIGZyb20gZml2ZSBzYW1wbGUgZ2FtZXMuIFVzaW5nIGdncG9pbnQsIHdlIHBsb3R0ZWQgdGhlIHNjYXR0ZXIgcGxvdCBvZiB0aGUgbWFya2V0IHZvbHVtZSBvdmVyIGEgcGVyaW9kIG9mIGEgZmV3IGhvdXJzIGJlZm9yZSBhbmQgYWZ0ZXIgdGhlIHN0YXJ0IG9mIHRoZSBnYW1lLCBhbmQgd2UgaW5kaWNhdGVkIHRoZSBzdGFydCB0aW1lIHdpdGggYSB2ZXJ0aWNhbCBsaW5lIG9uIHRoZSBncmFwaC4gVGhlIHZhbHVlcyBmb3Igdm9sdW1lIGFyZSB2ZXJ5IGxhcmdlIGFuZCB2YXJpZWQsIHdoaWNoIG1ha2VzIHRoZSBncmFwaHMgZGlmZmljdWx0IHRvIHJlYWQuIFRvIG1ha2UgdGhlbSBtb3JlIGRpZ2VzdGlibGUsIHdlIGluc3RlYWQgdXNlZCB0aGUgbG9nIG9mIHZvbHVtZSBhcyB0aGUgZGVwZW5kZW50IHZhcmlhYmxlLCBnaXZpbmcgdXMgc21hbGxlciBudW1iZXJzLiBXZSBmb3VuZCB0aGF0LCBpbiBnZW5lcmFsLCB0aGVyZSBpcyBhIHNsaWdodCBkaXAgaW4gdGhlIHZvbHVtZSBhcm91bmQgdGhlIHN0YXJ0IHRpbWUgb2YgdGhlIGdhbWUuIFRoaXMgYWdyZWVzIHdpdGggZmluZGluZ3MgZnJvbSBvdXIgcmVzZWFyY2ggdGhhdCBzdG9jayBtYXJrZXQgYWN0aXZpdHkgZHJvcHMgZHVycmluZyB0aGUgV29ybGQgQ3VwIGFzIG1vcmUgYXR0ZW50aW9uIGlzIGRpcmVjdGVkIHRvd2FyZHMgdGhlIGdhbWVzLiBXZSBhbHNvIHVzZWQgc2NhdHRlciBwbG90cyB0byBsb29rIGF0IHRoZSBhdmVyYWdlIHByaWNlIG9mIHN0b2NrcyBvdmVyIGEgcmFuZ2Ugb2YgdGltZSBhcm91bmQgdGhlIHN0YXJ0IHRpbWUgb2Ygc2FtcGxlIGdhbWVzLiBBcyBmb3IgdGhlIHZvbHVtZSBwbG90cywgd2UgaW5kaWNhdGVkIHRoZSBzdGFydCB0aW1lIG9mIHRoZSBnYW1lIHdpdGggYSB2ZXJ0aWNhbCBsaW5lIG9uIHRoZSBncmFwaC4gVGhlIGZpZ3VyZXMgc2hvdyB0aGF0IHRoZSBhdmVyYWdlIHByaWNlIHRlbmRzIHRvIGRyb3AganVzdCBiZWZvcmUgdGhlIHN0YXJ0IG9mIHRoZSBnYW1lLCBhbmQgdGhlbiBpbmNyZWFzZS4gVGhlc2UgdHJlbmRzIGluIHByaWNlIGxlYWQgdXMgdG8gZXhwbG9yZSB0aGUgdGltZXMgaXQgd291bGQgYmUgYmVzdCB0byBib3RoIGJ1eSBhbmQgc2VsbCBzdG9ja3MuCgpcClwKCiMjIEp1c3QgVVNBIEdhbWVzCgpgYGB7cn0Kd29ybGRjdXBtYXRjaGVzVVNBaG9tZSA9IGZpbHRlcihjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgSG9tZS5UZWFtLk5hbWUgPT0gIlVTQSIpCndvcmxkY3VwbWF0Y2hlc1VTQWF3YXkgPSBmaWx0ZXIoY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMsIEF3YXkuVGVhbS5OYW1lID09ICJVU0EiKQp3b3JsZGN1cG1hdGNoZXNVU0EgPC0gdW5pb25fYWxsKHdvcmxkY3VwbWF0Y2hlc1VTQWF3YXksd29ybGRjdXBtYXRjaGVzVVNBaG9tZSkKd29ybGRjdXBtYXRjaGVzVVNBCmBgYAoKYGBge3J9CmdhbWUxVVNBIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCB3b3JsZGN1cG1hdGNoZXNVU0EsIDEsIDMpCnZvbHVtZXNwMVVTQSA8LSBnZ3Bsb3QoZ2FtZTFVU0EpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1sb2codm9sdW1lKSksIGNvbG9yID0icmVkIikgKyBnZW9tX3ZsaW5lKHhpbnRlcmNlcHQ9IHdvcmxkY3VwbWF0Y2hlc1VTQSREYXRldGltZVsxXSkrIGdndGl0bGUoIlZvbHVtZSBvdmVyIFRpbWUsIFVTQSBHYW1lIDEsIDIwMTAiKQp2b2x1bWVzcDFVU0EKYGBgCgpgYGB7cn0KZ2FtZTJVU0EgPC0gZ2V0U3B5QW5kR2FtZURhdGFGb3JPbmVHYW1lKHNweWRhdGEsIHdvcmxkY3VwbWF0Y2hlc1VTQSwgMiwgMykKdm9sdW1lc3AyVVNBIDwtIGdncGxvdChnYW1lMlVTQSkgKyBnZW9tX3BvaW50KG1hcHBpbmcgPSBhZXMoeD1kYXRlLCB5PWxvZyh2b2x1bWUpKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gd29ybGRjdXBtYXRjaGVzVVNBJERhdGV0aW1lWzJdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgVVNBIEdhbWUgMiwgMjAxNCIpCnZvbHVtZXNwMlVTQQpgYGAKCmBgYHtyfQpnYW1lM1VTQSA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgd29ybGRjdXBtYXRjaGVzVVNBLCAzLCAzKQp2b2x1bWVzcDNVU0EgPC0gZ2dwbG90KGdhbWUzVVNBKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9dm9sdW1lKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gd29ybGRjdXBtYXRjaGVzVVNBJERhdGV0aW1lWzNdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgVVNBIEdhbWUgMiwgMjAxMCIpCnZvbHVtZXNwM1VTQQpgYGAKCmBgYHtyfQpnYW1lNFVTQSA8LSBnZXRTcHlBbmRHYW1lRGF0YUZvck9uZUdhbWUoc3B5ZGF0YSwgd29ybGRjdXBtYXRjaGVzVVNBLCA0LCAzKQp2b2x1bWVzcDRVU0EgPC0gZ2dwbG90KGdhbWU0VVNBKSArIGdlb21fcG9pbnQobWFwcGluZyA9IGFlcyh4PWRhdGUsIHk9dm9sdW1lKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gd29ybGRjdXBtYXRjaGVzVVNBJERhdGV0aW1lWzRdKSsgZ2d0aXRsZSgiVm9sdW1lIG92ZXIgVGltZSwgVVNBIEdhbWUgMSwgMjAxNCIpCnZvbHVtZXNwNFVTQQpgYGAKCmBgYHtyfQpwcmljZXNwNFVTQSA8LSBnZ3Bsb3QoZ2FtZTRVU0EpICsgZ2VvbV9wb2ludChtYXBwaW5nID0gYWVzKHg9ZGF0ZSwgeT1hdmVyYWdlKSwgY29sb3IgPSJyZWQiKSArIGdlb21fdmxpbmUoeGludGVyY2VwdD0gd29ybGRjdXBtYXRjaGVzVVNBJERhdGV0aW1lWzRdKSsgZ2d0aXRsZSgiUHJpY2Ugb3ZlciBUaW1lLCBVU0EgR2FtZSAxLCAyMDE0IikKcHJpY2VzcDRVU0EKYGBgCgojIElzIHRoZXJlIGEgd2F5IHRvIG1ha2UgbW9uZXkgZHVyaW5nIFdvcmxkIEN1cCBHYW1lcz8KCiMgV2hhdCB0aW1lIHNob3VsZCB5b3UgbG9vayB0byBzZWxsPwoKYGBge3J9CnByaWNlX2xpc3QgPSBjKCkKdGltZV9saXN0ID0gYygpCmZvciAoZ2FtZSBpbiAxOm5yb3coY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMpKSB7CiAgcHJpY2VfZ2FtZV9kYXRhIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgZ2FtZSwgMykKICBoaWdoZXN0ZGF0YXBvaW50ID0gcHJpY2VfZ2FtZV9kYXRhW3doaWNoLm1heChwcmljZV9nYW1lX2RhdGEkYXZlcmFnZSksXQogIGhpZ2hlc3RwcmljZWZvcmdhbWUgPC0gaGlnaGVzdGRhdGFwb2ludCRhdmVyYWdlCiAgdGltZSA8LSBoaWdoZXN0ZGF0YXBvaW50JCJ0aW1lLmZyb20uZ2FtZSIKICBwcmljZV9saXN0ID0gYXBwZW5kKHByaWNlX2xpc3QsIGhpZ2hlc3RwcmljZWZvcmdhbWUpCiAgdGltZV9saXN0ID0gYXBwZW5kKHRpbWVfbGlzdCwgdGltZSkKfQpgYGAKCmBgYHtyfQpvcHRpbWFsX3NlbGxpbmcuZGYgPC0gZGF0YS5mcmFtZSgicHJpY2UiID0gcHJpY2VfbGlzdCwgInRpbWUiID0gdGltZV9saXN0KQpvcHRpbWFsX3NlbGxpbmcuZGYKYGBgCgpEbyBUSGlzIGZvciBPcHRpbWFsIEJ1eWluZyB0aW1lPwoKYGBge3J9CmdncGxvdChvcHRpbWFsX3NlbGxpbmcuZGYpICsgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4PSB0aW1lKSkgKyBnZ3RpdGxlKCJIb3cgT2Z0ZW4gQmVzdCBTZWxsaW5nIFRpbWUgaXMgdnMuIFRpbWUgRnJvbSBHYW1lIikKYGBgCgojIFdoYXQgdGltZSBzaG91bGQgeW91IGxvb2sgdG8gYnV5PwoKYGBge3J9CnByaWNlX2xpc3QgPSBjKCkKdGltZV9saXN0ID0gYygpCmZvciAoZ2FtZSBpbiAxOm5yb3coY2xlYW5lZF93b3JsZGN1cG1hdGNoZXMpKSB7CiAgcHJpY2VfZ2FtZV9kYXRhIDwtIGdldFNweUFuZEdhbWVEYXRhRm9yT25lR2FtZShzcHlkYXRhLCBjbGVhbmVkX3dvcmxkY3VwbWF0Y2hlcywgZ2FtZSwgMykKICBsb3dlc3RkYXRhcG9pbnQgPSBwcmljZV9nYW1lX2RhdGFbd2hpY2gubWluKHByaWNlX2dhbWVfZGF0YSRhdmVyYWdlKSxdCiAgbG93ZXN0cHJpY2Vmb3JnYW1lIDwtIGxvd2VzdGRhdGFwb2ludCRhdmVyYWdlCiAgdGltZSA8LSBsb3dlc3RkYXRhcG9pbnQkInRpbWUuZnJvbS5nYW1lIgogIHByaWNlX2xpc3QgPSBhcHBlbmQocHJpY2VfbGlzdCwgbG93ZXN0cHJpY2Vmb3JnYW1lKQogIHRpbWVfbGlzdCA9IGFwcGVuZCh0aW1lX2xpc3QsIHRpbWUpCn0KYGBgCgpgYGB7cn0Kb3B0aW1hbF9idXlpbmcuZGYgPC0gZGF0YS5mcmFtZSgicHJpY2UiID0gcHJpY2VfbGlzdCwgInRpbWUiID0gdGltZV9saXN0KQpnZ3Bsb3Qob3B0aW1hbF9idXlpbmcuZGYpICsgZ2VvbV9oaXN0b2dyYW0obWFwcGluZyA9IGFlcyh4PSB0aW1lKSkgKyBnZ3RpdGxlKCJIb3cgT2Z0ZW4gQmVzdCBCdXlpbmcgVGltZSBpcyB2cy4gVGltZSBGcm9tIEdhbWUiKQpgYGAKCkFub3RoZXIgaWRlYSB3ZSB3YW50ZWQgdG8gZXhwbG9yZSB3YXMgdGhlIG9wdGltYWwgYnV5aW5nIGFuZCBzZWxsaW5nIHRpbWVzIGZvciBTUFkuIFRoZSBvcHRpbWFsIGJ1eWluZyB0aW1lIHdvdWxkIGJlIHdoZW4gdGhlIFNQWSBwcmljZSBpcyB0aGUgbG93ZXN0IGFuZCB0aGUgb3B0aW1hbCBzZWxsaW5nIHRpbWUgd291bGQgYmUgd2hlbiB0aGUgU1BZIHByaWNlIGlzIHRoZSBoaWdoZXN0LiBJbiBvcmRlciB0byBmaW5kIHRoZSBvcHRpbWFsIHRpbWVzIGZyb20gdGhlIGdhbWUsIHdlIGZvdW5kIHRoZSBtYXhpbXVtIGFuZCBtaW5pbXVtIHByaWNlIG9mIFNQWSBkdXJpbmcgZWFjaCBnYW1lLiBGcm9tIHRoZXJlLCB3ZSBmb3VuZCB0aGUgY29ycmVzcG9uZGluZyB0aW1lIGZyb20gZ2FtZSBmb3IgdGhlc2UgbWF4aW11bSBhbmQgbWluaW11bSBwcmljZSB2YWx1ZXMuIFdpdGggdGhpcyBkYXRhLCB3ZSBjcmVhdGVkIHR3byBoaXN0b2dyYW1zOiBvbmUgdGhhdCBkZW1vbnN0cmF0ZXMgdGhlIG9wdGltYWwgYnV5aW5nIHRpbWVzIGZyb20gYSB3b3JsZCBjdXAgZ2FtZSBhbmQgYW5vdGhlciB0aGF0IGRlbW9uc3RyYXRlZCB0aGUgb3B0aW1hbCBzZWxsaW5nIHRpbWVzIGZyb20gYSB3b3JsZCBjdXAgZ2FtZS4gVGhlIGhpc3RvZ3JhbXMgZGlzcGxheSB0aGUgdGltZSBmcm9tIGdhbWUgb24gdGhlIHgtYXhpcyBhbmQgc2hvdyB0aGUgYW1vdW50IG9mIGhhbWVzIHRoYXQgaGF2ZSB0aGVpciBvcHRpbWFsIHNlbGxpbmcgb3IgYnV5aW5nIHRpbWUgYXQgdGhhdCB0aW1lIHZhbHVlLiBGb3IgdGhlIG9wdGltYWwgc2VsbGluZyBoaXN0b2dyYW0sIHRoZXJlIGFyZSBwZWFrcyBhdCAxMCwwMDAgc2Vjb25kcyBhbmQgNSwwMDAgc2Vjb25kcyBiZWZvcmUgdGhlIGdhbWUuIFRoZXNlIHR3byB0aW1lIHZhbHVlcyBjb3JyZXNwb25kIHRvIGFyb3VuZCB0aHJlZSBob3VycyBiZWZvcmUgdGhlIGdhbWUgYW5kIG9uZSBhbmQgYSBoYWxmIGhvdXJzIGJlZm9yZSB0aGUgZ2FtZSwgcmVzcGVjdGl2ZWx5LiBUaGVyZSB3ZXJlIG90aGVyIG91dGxpZXJzIGluIHRoZSBoaXN0b2dyYW0sIGJ1dCB0aGVzZSB0d28gdmFsdWVzIHNlZW0gdG8gYmUgdGhlIGJlc3QgdGltZXMgYXJvdW5kIGEgd29ybGQgY3VwIGdhbWUgdG8gc2VsbCBTUFkgc3RvY2ssIGJhc2VkIG9uIG91ciBkYXRhLiBGb3IgdGhlIG9wdGltYWwgYnV5aW5nIGhpc3RvZ3JhbSwgdGhlcmUgd2FzIGEgbGFyZ2UgcGVhayBhcm91bmQgMTAsMDAwIHNlY29uZHMgYmVmb3JlIHRoZSBnYW1lLCB3aGljaCBpcyB0aHJlZSBob3VycyBiZWZvcmUgdGhlIGdhbWUuIFRoZSBoaXN0b2dyYW0gaXMgc2tld2VkIHJpZ2h0LCBzbyB0aGUgdGltZXMgd2hlcmUgdGhlIFNQWSBwcmljZSB3YXMgdGhlIGxvd2VzdCB3YXMgYmVmb3JlIHRoZSBnYW1lLiBGcm9tIHRoaXMgaGlzdG9ncmFtLCBpdCBhcHBlYXJzIHRoYXQgdGhlIGJlc3QgdGltZSB0byBidXkgU1BZIHN0b2NrIGlzIHRocmVlIGhvdXJzIGJlZm9yZSB0aGUgc3RhcnQgb2YgYSB3b3JsZCBjdXAgZ2FtZS7CoAoKXApcCgojIERvZXMgdGhlIGltcG9ydGFuY2Ugb2YgdGhlIGdhbWUgbWF0dGVyIGluIHRoZSB0b3RhbCBhbW91bnQgb2YgdHJhZGVzPwoKYGBge3J9CiNCb3ggUGxvdCBmb3IgVHJhZGVzCmdncGxvdChhbGxzcHlkYXRhLCBhZXMobG9nKHZvbHVtZSksIFN0YWdlLCBmaWxsID0gU3RhZ2UpKSArIGdlb21fYm94cGxvdCgpICsgZ2d0aXRsZSgiTG9nKFZvbHVtZSkgdnMuIFN0YWdlIE9mIEdhbWUgYW5kIEdyb3VwcyIpCmBgYAoKYGBge3J9CmFsbHNweWRhdGEkU3RhZ2VbZ3JlcGwoIkdyb3VwIiwgYWxsc3B5ZGF0YSRTdGFnZSwgZml4ZWQgPSBUUlVFKV0gID0gIkdyb3VwIgpnZ3Bsb3QoYWxsc3B5ZGF0YSwgYWVzKGxvZyh2b2x1bWUpLCBTdGFnZSwgZmlsbCA9IFN0YWdlKSkgKyBnZW9tX2JveHBsb3QoKSArIGdndGl0bGUoIkxvZyhWb2x1bWUpIHZzLiBTdGFnZSBPZiBHYW1lIikKYGBgCg==